#include "mytcpsocket.h"
#include <QDebug>
#include <mytcpserver.h>
#include <QStringList>
#include <QDir>//专门用于操作文件夹
#include <QFileInfoList>

MyTcpSocket::MyTcpSocket()
{
    connect(this,SIGNAL(readyRead()),this,SLOT(recvMsg())); //socket数据本身进行处理readyread -> slot
    connect(this,SIGNAL(disconnected()),this,SLOT(clientOffline()));//只要检测倒下线，对应的socket就会发出discnonnected，然后转交到对应函数处理。
    m_bUpload = false;
    m_pTimer = new QTimer;
    connect(m_pTimer,SIGNAL(timeout()),this,SLOT(sendFileToClient()));

}

QString MyTcpSocket::getName()
{
    return m_strName;
}

void MyTcpSocket::copyDir(QString strSrcDir, QString strDestDir)
{
    QDir dir;
    dir.mkdir(strDestDir);
    dir.setPath(strSrcDir);
    QFileInfoList fileInfoList =   dir.entryInfoList();//获取目录中的文件信息
    QString srcTmp;
    QString destTmp;
    for(int i = 0;i<fileInfoList.size();++i)
    {
        qDebug() << "filename:" << fileInfoList[i].fileName();
        if(fileInfoList[i].isFile())
        {
            srcTmp  = strSrcDir +'/' +fileInfoList[i].fileName();
            destTmp = strDestDir + '/' +fileInfoList[i].fileName();
            QFile::copy(srcTmp,destTmp);//源，目的
        }
        else if(fileInfoList[i].isDir())
        {
            if(QString(".") == fileInfoList[i].fileName() || QString("..") == fileInfoList[i].fileName()) continue;//如果是.或者..,表示这个是上级目录，不用在意
            srcTmp  = strSrcDir +'/' +fileInfoList[i].fileName();
            destTmp = strDestDir + '/' +fileInfoList[i].fileName();
            copyDir(srcTmp,destTmp);
        }
    }
}

void MyTcpSocket::recvMsg()//服务器接收信息，判断消息类型，服务器端通过tcpsocket发送过来在这里接收
{
    //判断一下
    if(!m_bUpload)//未上传的情况下
    {
        qDebug() << this->bytesAvailable();//获取数据的大小，可读数据的大小
        //↓收数据
        uint uiPDULen =0;
        this->read((char*)&uiPDULen,sizeof(uint));
        uint uiMsgLen = uiPDULen - sizeof(PDU);//实际消息的长度
        PDU *pdu = mkPDU(uiMsgLen);
        this->read((char*)pdu + sizeof(uint),uiPDULen - sizeof(uint));
        //↑
        switch(pdu->uiMsgType)//判断消息类型
        {
        case ENUM_MSG_TYPE_REGIST_REQUEST://如果是注册请求
        {
            char caName[32] = {'\0'};
            char caPwd[32] = {'\0'};
            strncpy(caName,pdu->caData,32);
            strncpy(caPwd,pdu->caData+32,32);
            bool ret = OpeDB::getInstance().handleRegist(caName,caPwd);//交给刚刚创建的数据库函数来处理
            PDU *respPdu = mkPDU(0);//申请动态空间,给0相当于caData的64位消息足够，不需要在进行动态数组的分配,也就是回复的信息就是放在caData就可以,实际消息给0
            respPdu->uiMsgType = ENUM_MSG_TYPE_REGIST_RESPOND;
            if(ret)
            {
                strcpy(respPdu->caData,REGIST_OK);
                QDir dir;
                qDebug() <<"create dir "<<dir.mkdir(QString("./%1").arg(caName));//默认是在当前项目的文件目录下
            }
            else
            {
                strcpy(respPdu->caData,REGIST_FAILED);
            }
            write((char*)respPdu,respPdu->uiPDULen);
            free(respPdu);
            respPdu = nullptr;
            break;
        }
        case ENUM_MSG_TYPE_LOGIN_REQUEST://如果是登录请求
        {//去数据库查看是否出现
            char caName[32] = {'\0'};
            char caPwd[32] = {'\0'};
            strncpy(caName,pdu->caData,32);//用户名和密码从pdu中拷贝出来
            strncpy(caPwd,pdu->caData+32,32);
            bool ret = OpeDB::getInstance().handleLogin(caName,caPwd);
            PDU *respPdu = mkPDU(0);//申请动态空间,给0相当于caData的64位消息足够，不需要在进行动态数组的分配,也就是回复的信息就是放在caData就可以,实际消息给0
            respPdu->uiMsgType = ENUM_MSG_TYPE_LOGIN_RESPOND;
            if(ret)
            {
                strcpy(respPdu->caData,LOGIN_OK);
                m_strName = caName;//拷贝下名字
            }
            else
            {
                strcpy(respPdu->caData,LOGIN_FAILED);
            }
            write((char*)respPdu,respPdu->uiPDULen);
            free(respPdu);
            respPdu = nullptr;
            break;
        }
        case ENUM_MSG_TYPE_ALLONLINE_REQUEST://收到全部用户的请求
        {
            QStringList ret = OpeDB::getInstance().handleAllOnline();//通过单例模式调用
            uint uiMsgLen = ret.size() * 32;
            PDU *resPdu = mkPDU(uiMsgLen);//产生pdu，也就是通过pdu申请一个内存空间
            resPdu->uiMsgType = ENUM_MSG_TYPE_ALLONLINE_RESPOND;
            //将用户名循环拷贝到空间里
            for(int i = 0;i < ret.size();++i)
            {
                memcpy((char*)(resPdu->caMsg) + i*32,
                       ret.at(i).toStdString().c_str(),
                       ret.at(i).size());//依次向后存储,at获得第几个数据
            }
            write((char*)resPdu,resPdu->uiPDULen);//结果返回给客户端
            free(resPdu);
            resPdu = nullptr;
            break;
        }
        case ENUM_MSG_TYPE_SEARCH_USR_REQUEST:
        {
            //去数据库里面查找
            int ret = OpeDB::getInstance().handleSearchUser(pdu->caData);//用户名密码什么都存在cadata里面
            PDU *respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_SEARCH_USR_RESPOND;//查找回复
            if(ret == -1)
            {
                strcpy(respdu->caData,SEARCH_USER_NO);//函数返回值为-1
            }
            else if(ret == 1)
            {
                strcpy(respdu->caData,SEARCH_USER_ONLINE);//在线，在协议里定义过
            }
            else if(ret == 0)
            {
                strcpy(respdu->caData,SEARCH_USER_OFFLINE);//用户存在但是离线
            }
            write((char*)respdu,respdu->uiPDULen); //结果返回给客户端
            free(respdu);
            respdu = nullptr;
            break;
        }
        case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:
        {
            //依然是到数据库操作
            //添加好友请求的处理
            char caPerName[32] = {'\0'};
            char caName[32] = {'\0'};
            strncpy(caPerName,pdu->caData,32);
            strncpy(caName,pdu->caData+32,32);
            int ret = OpeDB::getInstance().handleAddFriend(caPerName,caName);
            PDU *respdu = nullptr;
            if(ret == -1)//针对情况给客户端回复
            {
                respdu = mkPDU(0);
                respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;
                strcpy(respdu->caData,ADD_FRIEND_NO_EXIST);
                write((char*)respdu,respdu->uiPDULen);//结果返回给客户端
                free(respdu);
                respdu = nullptr;

            }
            else if(ret == 0)
            {
                respdu = mkPDU(0);
                respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;
                strcpy(respdu->caData,EXISTED_FRIEND);
                write((char*)respdu,respdu->uiPDULen);//结果返回给客户端
                free(respdu);
                respdu = nullptr;

            }
            else if(ret == 1)
            {
                //在线需要转发，需要接受socket
                MyTcpServer::getInstance().resend(caPerName,pdu);

            }
            else if(ret == 2)
            {
                respdu = mkPDU(0);
                respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;
                strcpy(respdu->caData,ADD_FRIEND_OFFLINE);
                write((char*)respdu,respdu->uiPDULen);//结果返回给客户端
                free(respdu);
                respdu = nullptr;

            }
            else if(ret == 3)
            {
                respdu = mkPDU(0);
                respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;
                strcpy(respdu->caData,ADD_FRIEND_NO_EXIST);
                write((char*)respdu,respdu->uiPDULen);//结果返回给客户端..   2
                free(respdu);
                respdu = nullptr;
            }
            break;
        }
        case ENUM_MSG_TYPE_ADD_FRIEND_REFUSE:
        {
            char caName[32] = {'\0'};
            strncpy(caName,pdu->caData+32,32);
            MyTcpServer::getInstance().resend(caName,pdu);
            break;
        }
        case ENUM_MSG_TYPE_FLUSH_FRIEND_REQUEST:
        {//需要根据名字去数据库提取信息
            char caName[32] = {'\0'};
            strncpy(caName,pdu->caData,32);
            QStringList ret =  OpeDB::getInstance().handleFlushFriend(caName);
            uint uiMsgLen = ret.size() * 32;
            PDU *respdu = mkPDU(uiMsgLen);
            respdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FRIEND_RESPOND;
            for(int i = 0;i <ret.size();i++)
            {
                memcpy((char*) (respdu->caMsg) + i*32,ret.at(i).toStdString().c_str(),ret.at(i).size());


            }
            //发送数据
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;
            break;
        }
        case ENUM_MSG_TYPE_DELETE_FRIEND_REQUEST:
        {
            //对数据库操作之后还要对对方进行通知
            char caSelfName[32] = {'\0'};
            char caFriendName[32] = {'\0'};
            strncpy(caSelfName,pdu->caData,32);
            strncpy(caFriendName,pdu->caData+32,32);//memcpy直接对内存操作，无所谓类型，而strcpy是对char*

            OpeDB::getInstance().handleDelFriend(caSelfName,caFriendName);
            PDU *respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_DELETE_FRIEND_RESPOND;
            strcpy(respdu->caData,DEL_FRIEND_OK);
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;
            //如果在线就回复给对方
            MyTcpServer::getInstance().resend(caFriendName,pdu);//消息转发


            break;
        }
        case ENUM_MSG_TYPE_PRIVATE_CHAT_FRIEND_REQUEST:
        {
            char caPerName[32] = {'\0'};
            memcpy(caPerName,pdu->caData+32,32);
            qDebug()<<caPerName;
            MyTcpServer::getInstance().resend(caPerName,pdu);
            break;
        }
        case ENUM_MSG_TYPE_GROUP_CHAT_FRIEND_REQUEST://服务器接收到客户端传送的uimsgtype请求
        {
            //逻辑：首先考虑去服务器查询那些好友在线，然后进行处理
            char caName[32] = {'\0'};//获得发送端的名字
            strncpy(caName,pdu->caData,32);
            //通过刷新获取在线的好友
            QStringList onlineFriend = OpeDB::getInstance().handleFlushFriend(caName);//将在线的好友显示出来
            QString tmp;
            for(int i = 0;i < onlineFriend.size();i++)
            {
                tmp = onlineFriend.at(i);
                MyTcpServer::getInstance().resend(tmp.toStdString().c_str(),pdu);//第几个名字，找到了就进行转发
            }

            break;
        }
        case ENUM_MSG_TYPE_CREATE_DIR_REQUEST:
        {
            QDir dir;
            QString strCurPath = QString("%1").arg((char*)pdu->caMsg);
            qDebug() << strCurPath;
            bool ret = dir.exists(strCurPath);
            PDU *respdu = nullptr;
            if(ret)//当前目录存在
            {
                char caNewDir[32] ={'\0'};//新的路径
                memcpy(caNewDir,pdu->caData+32,32);
                QString strNewPath = strCurPath+"/"+caNewDir;
                qDebug() <<strNewPath;
                ret = dir.exists(strNewPath);
                qDebug() <<"-->"<< ret;
                if(ret)//创建的文件已经存在
                {
                    respdu = mkPDU(0);
                    respdu->uiMsgType = ENUM_MSG_TYPE_CREATE_DIR_RESPOND;//创建路径的回复
                    strcpy(respdu->caData,FILE_NAME_EXIST);//文件名称已经存在
                }
                else//创建的文件不存在
                {
                    dir.mkdir(strNewPath);//把新的这个目录创建出来
                    respdu = mkPDU(0);
                    respdu->uiMsgType = ENUM_MSG_TYPE_CREATE_DIR_RESPOND;//创建路径的回复
                    strcpy(respdu->caData,CREATE_DIR_OK);//路径不存在
                }
            }
            else//当前目录不存在
            {
                respdu = mkPDU(0);
                respdu->uiMsgType = ENUM_MSG_TYPE_CREATE_DIR_RESPOND;//创建路径的回复
                strcpy(respdu->caData,DIR_NO_EXIST);//路径不存在
            }
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;

            break;
        }
        case ENUM_MSG_TYPE_FLUSH_FILE_REQUEST:
        {
            //路径需要定义一个数组或者申请一个空间，QString 在产生的时候没有空间
            char *pCurPath = new char[pdu->uiMsgLen];
            memcpy(pCurPath,pdu->caMsg,pdu->uiMsgLen);//把camsg的内容从pdu种拷贝出来
            QDir dir(pCurPath);//操作的路径
            QFileInfoList fileInfoList =  dir.entryInfoList();//默认值即可
            int iFileCount = fileInfoList.size();
            PDU *respdu = mkPDU(sizeof(FileInfo) * iFileCount);//一个文件一个结构体，那么多少个文件就是多少个结构体的长度
            respdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FILE_RESPOND;//传到客户端的消息类型
            FileInfo *pFileInfo = nullptr;
            QString strFileName;
            for(int i = 0;i<iFileCount;++i)
            {
                //结构体拷贝进pdu
                pFileInfo = (FileInfo*)(respdu->caMsg) + i;//结构体是连续的，所以，每次跳过一次filename的大小
                strFileName = fileInfoList[i].fileName();
                memcpy(pFileInfo->caFileName,strFileName.toStdString().c_str(),strFileName.size());
                if(fileInfoList[i].isDir())
                {
                    pFileInfo->iFileType = 0;//表示是一个文件夹

                }
                else if(fileInfoList[i].isFile())
                {
                    pFileInfo->iFileType = 1;//是一个文件类型
                }
                qDebug() << fileInfoList[i].fileName()
                         <<fileInfoList[i].size()
                        <<"文件夹 ：" <<fileInfoList[i].isDir()
                       <<"常规文件 :" <<fileInfoList[i].isFile();
            }
            //发送给客户端
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;
            break;
        }
        case ENUM_MSG_TYPE_DEL_DIR_REQUEST:
        {
            //要删除的话，首先需要将路径和文件名进行拼接
            char caName[32] = {'\0'};
            strcpy(caName,pdu->caData);//传过来的文件名先放入caname
            char *pPath = new char[pdu->uiMsgLen];//申请的堆区空间就是路径的长度
            memcpy(pPath,pdu->caMsg,pdu->uiMsgLen);
            QString strPath = QString("%1/%2").arg(pPath).arg(caName);//路径+名字
            qDebug() << strPath;

            //删除的时候要判断是不是路径，还是文件，两者删除的方式不同
            QFileInfo fileInfo(strPath);
            bool ret = false;
            if(fileInfo.isDir())
            {
                QDir dir;
                dir.setPath(strPath);//通过dir对象来删除
                ret = dir.removeRecursively();//删除路径包括里面的所有文件，如果文件夹里有子目录的话用这个，如果没有，单纯的是一个空文件夹可以用rmdir
            }
            else if(fileInfo.isFile())//是常规文件，不是文件路径
            {
                ret = false;
            }
            PDU *respdu = nullptr;//用于给客户端回复的pdu
            if(ret)
            {
                respdu = mkPDU(strlen(DEL_DIR_OK) + 1);//成功，就回复删除成功
                respdu->uiMsgType = ENUM_MSG_TYPE_DEL_DIR_RESPOND;
                memcpy(respdu->caData,DEL_DIR_OK,strlen(DEL_DIR_OK));

            }
            else
            {
                respdu = mkPDU(strlen(DEL_DIR_FAILED) + 1);//成功，就回复删除成功
                respdu->uiMsgType = ENUM_MSG_TYPE_DEL_DIR_RESPOND;
                memcpy(respdu->caData,DEL_DIR_FAILED,strlen(DEL_DIR_FAILED));
            }
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;//发送给客户端

            break;
        }
        case ENUM_MSG_TYPE_RENAME_FILE_REQUEST:
        {
            char caOldName[32] = {'\0'};
            char caNewName[32] = {'\0'};
            strncpy(caOldName,pdu->caData,32);
            strncpy(caNewName,pdu->caData+32,32);

            char *pPath = new char[pdu->uiMsgLen];
            memcpy(pPath,pdu->caMsg,pdu->uiMsgLen);
            QString strOldPath  = QString("%1/%2").arg(pPath).arg(caOldName);
            QString strNewPath  = QString("%1/%2").arg(pPath).arg(caNewName);
            qDebug() <<strOldPath;
            qDebug() << strNewPath;
            QDir dir;
            bool ret = dir.rename(strOldPath,strNewPath);//形参1 old 形参2 new
            PDU *respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_RENAME_FILE_RESPOND;
            if(ret)
            {
                strcpy(respdu->caData,RENAME_FILE_OK);
            }
            else
            {
               strcpy(respdu->caData,RENAM_FILE_FAILED);
            }
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;

            break;
        }
        case ENUM_MSG_TYPE_ENTER_DIR_REQUEST:
        {
            char caEnterName[32] = {'\0'};
            strncpy(caEnterName,pdu->caData,32);

            char *pPath = new char[pdu->uiMsgLen];
            memcpy(pPath,pdu->caMsg,pdu->uiMsgLen);
            QString strPath  = QString("%1/%2").arg(pPath).arg(caEnterName);
            qDebug() << strPath;
            QFileInfo fileInfo(strPath);
            PDU *respdu = nullptr;
            if(fileInfo.isDir())
            {
                QDir dir(strPath);//操作的路径
                QFileInfoList fileInfoList =  dir.entryInfoList();//默认值即可
                int iFileCount = fileInfoList.size();
                PDU *respdu = mkPDU(sizeof(FileInfo) * iFileCount);//一个文件一个结构体，那么多少个文件就是多少个结构体的长度
                respdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FILE_RESPOND;//传到客户端的消息类型,更新文件夹
                FileInfo *pFileInfo = nullptr;
                QString strFileName;
                for(int i = 0;i<iFileCount;++i)
                {
                    //结构体拷贝进pdu
                    pFileInfo = (FileInfo*)(respdu->caMsg) + i;//结构体是连续的，所以，每次跳过一次filename的大小
                    strFileName = fileInfoList[i].fileName();
                    memcpy(pFileInfo->caFileName,strFileName.toStdString().c_str(),strFileName.size());
                    if(fileInfoList[i].isDir())
                    {
                        pFileInfo->iFileType = 0;//表示是一个文件夹

                    }
                    else if(fileInfoList[i].isFile())
                    {
                        pFileInfo->iFileType = 1;//是一个文件类型
                    }
                    qDebug() << fileInfoList[i].fileName()
                             <<fileInfoList[i].size()
                            <<"文件夹 ：" <<fileInfoList[i].isDir()
                           <<"常规文件 :" <<fileInfoList[i].isFile();
                }
                //发送给客户端
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = nullptr;
            }
            else if(fileInfo.isFile())//是常规文件的情况下
            {
                respdu = mkPDU(0);
                respdu->uiMsgType = ENUM_MSG_TYPE_ENTER_DIR_RESPOND;
                strcpy(pdu->caData,ENTER_DIR_FAILED);
                write((char*)respdu,respdu->uiPDULen);
                free(respdu);
                respdu = nullptr;
            }
            break;
        }
        case ENUM_MSG_TYPE_UPLOAD_DIR_REQUEST:
        {
            char caFileName[32] = {'\0'};
            qint64 fileSize = 0;
            sscanf(pdu->caData,"%s %lld",caFileName,&fileSize);
            char *pPath = new char[pdu->uiMsgLen];//申请的堆区空间就是路径的长度
            memcpy(pPath,pdu->caMsg,pdu->uiMsgLen);//路径
            QString strPath = QString("%1/%2").arg(pPath).arg(caFileName);//路径+名字,拼接字符串
            qDebug() << strPath;
            delete []pPath;//new 完了记得释放掉
            pPath = nullptr;

            m_file.setFileName(strPath);

            //以只写入的方式打开文件，如文件不存在，则自动创建文件
            if(m_file.open(QIODevice::WriteOnly))
            {
                m_bUpload = true;//设置为真，表示为上传文件状态
                m_iTotal = fileSize;//总的大小
                m_iReceived = 0;
            }
            break;
        }
        case ENUM_MSG_TYPE_DEL_FILE_REQUEST:
        {
            char caName[32] = {'\0'};
            strcpy(caName,pdu->caData);//传过来的文件名先放入caname
            char *pPath = new char[pdu->uiMsgLen];//申请的堆区空间就是路径的长度
            memcpy(pPath,pdu->caMsg,pdu->uiMsgLen);
            QString strPath = QString("%1/%2").arg(pPath).arg(caName);//路径+名字
            qDebug() << strPath;

            //删除的时候要判断是不是路径，还是文件，两者删除的方式不同
            QFileInfo fileInfo(strPath);
            bool ret = false;
            if(fileInfo.isDir())
            {
                ret = false;//与文件夹相反

            }
            else if(fileInfo.isFile())//是常规文件，不是文件路径
            {
                QDir dir;
                ret = dir.remove(strPath);//删除成功就会变成true
            }
            PDU *respdu = nullptr;//用于给客户端回复的pdu
            if(ret)
            {
                respdu = mkPDU(strlen(DEL_FILE_OK) + 1);//成功，就回复删除成功
                respdu->uiMsgType = ENUM_MSG_TYPE_DEL_FILE_RESPOND;
                memcpy(respdu->caData,DEL_FILE_OK,strlen(DEL_FILE_OK));

            }
            else
            {
                respdu = mkPDU(strlen(DEL_FILE_FAILED) + 1);//成功，就回复删除成功
                respdu->uiMsgType = ENUM_MSG_TYPE_DEL_FILE_RESPOND;
                memcpy(respdu->caData,DEL_FILE_FAILED,strlen(DEL_FILE_FAILED));
            }
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;//发送给客户端
            break;
        }
        case ENUM_MSG_TYPE_DOWNLOAD_FILE_REQUEST:
        {
            char caFileName[32] = {'\0'};
            strcpy(caFileName,pdu->caData);
            char *pPath = new char[pdu->uiMsgLen];//申请的堆区空间就是路径的长度
            memcpy(pPath,pdu->caMsg,pdu->uiMsgLen);//路径
            QString strPath = QString("%1/%2").arg(pPath).arg(caFileName);//路径+名字,拼接字符串
            qDebug() << strPath;
            delete []pPath;//new 完了记得释放掉
            pPath = nullptr;
            QFileInfo fileInfo(strPath);
            qint64 fileSize = fileInfo.size();
            PDU *respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_DOWNLOAD_FILE_RESPOND;//服务器传送回去的回复
            sprintf(respdu->caData,"%s %lld",caFileName,fileSize);

            write((char *)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;

            m_file.setFileName(strPath);
            m_file.open(QIODevice::ReadOnly);
            m_pTimer->start(1000);

            break;
        }
        case ENUM_MSG_TYPE_SHARE_FILE_REQUEST:
        {
            //发送者名字
            char caSendName[32] = {'\0'};
            int num  = 0;
            sscanf(pdu->caData,"%s%d",caSendName,&num);
            int size = num*32;
            PDU *respdu = mkPDU(pdu->uiMsgLen - size);
            respdu->uiMsgType = ENUM_MSG_TYPE_SHARE_FILE_NOTE;
            strcpy(respdu->caData,caSendName);
            memcpy(respdu->caMsg,(char*)(pdu->caMsg) + size , pdu->uiMsgLen - size);
            char caRecvName[32] = {'\0'};
            for(int i = 0;i<num;++i)
            {
                memcpy(caRecvName,(char*)(pdu->caMsg) + i *32,32);
                MyTcpServer::getInstance().resend(caRecvName,respdu);


            }
            free(respdu);
            respdu = nullptr;
            //给发送者一个回复的信息
            respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_SHARE_FILE_RESPOND;
            strcpy(respdu->caData,"share file ok");
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;
            break;

        }
        case ENUM_MSG_TYPE_SHARE_FILE_NOTE_RESPOND:
        {
            //首先拷贝到目录里面去
            QString strRecvPath = QString("./%1").arg(pdu->caData);
            //共享者的文件路径
            QString strShareFilePath = QString("%1").arg((char*)(pdu->caMsg));
            int index = strShareFilePath.lastIndexOf('/');
            QString strFileName = strShareFilePath.right(strShareFilePath.size() - index - 1);
            strRecvPath = strRecvPath +'/' + strFileName;
            //进行文件属性的判断
            QFileInfo fileInfo(strShareFilePath);
            if(fileInfo.isFile())
            {
                QFile::copy(strShareFilePath,strRecvPath);
            }
            else if(fileInfo.isDir())
            {
                copyDir(strShareFilePath,strRecvPath);
            }


            break;
        }
        case ENUM_MSG_TYPE_MOVE_FILE_REQUEST:
        {
            char caFileName[32] = {'\0'};
            int srcLen = 0;
            int destLen = 0;
            sscanf(pdu->caData,"%d%d%s",&srcLen,&destLen,caFileName);
            char *pSrcPath = new char[srcLen+ 1];
            char *pDestPath = new char [destLen + 1];
            memset(pSrcPath,'\0',srcLen+1);
            memset(pDestPath,'\0',destLen + 1);
            memcpy(pSrcPath,pdu->caMsg,srcLen);
            memcpy(pDestPath,(char*)(pdu->caMsg)+srcLen+1,destLen);
            PDU *respdu = mkPDU(0);
            respdu->uiMsgType = ENUM_MSG_TYPE_MOVE_FILE_RESPOND;
            QFileInfo fileInfo(pDestPath);
            if(fileInfo.isDir())
            {
                strcat(pDestPath,"/");
                strcat(pDestPath,caFileName);

                bool ret =  QFile::rename(pSrcPath,pDestPath);
                if(ret)
                {
                    strcpy(respdu->caData,MOVE_FILE_OK);
                }
                else
                {
                    strcpy(respdu->caData,COMMON_ERR);
                }

            }
            else if(fileInfo.isFile())
            {
                strcpy(respdu->caData,MOVE_FILE_FAILED);
            }
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;
            break;
        }
        default:
            break;
        }
        free(pdu);
        pdu = nullptr;
    }
    else//进行上传文件
    {
        PDU *respdu = nullptr;
        respdu = mkPDU(0);
        respdu->uiMsgType = ENUM_MSG_TYPE_UPLOAD_DIR_RESPOND;
        //不是上传文件的状态
        //接受上传的数据
        QByteArray buff = readAll();//接收读到的数据
        m_file.write(buff);
        m_iReceived += buff.size();
        if(m_iTotal >= m_iReceived)//成功接收
        {
            //表示接收数据结束
            m_file.close();
            m_bUpload = false;
            strcpy(respdu->caData,UPLOAD_FILE_OK);
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;

        }
        else if(m_iTotal < m_iReceived)//总数据小于接收到的数据，说明接收出现问题
        {
            m_file.close();
            m_bUpload = false;
            strcpy(respdu->caData,UPLOAD_FILE_FAILED);
            write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = nullptr;
        }
    }

    //qDebug() << pdu->uiMsgType << (char*)(pdu->caMsg);//输出验证

    //qDebug() << caName << caPwd << pdu->uiMsgType;
}

void MyTcpSocket::clientOffline()//进行下线，牵扯到数据库
{
    //调用void函数
    OpeDB::getInstance().handleOffline(m_strName.toStdString().c_str());//先转换成cpp的string类型，然后再转换成char*型
    emit offLine(this);
}

void MyTcpSocket::sendFileToClient()
{
    char *pData = new char[4096];
    qint64 ret = 0;
    while(true)
    {
        ret = m_file.read(pData,4096);//有多少读多少，返回给ret
        if(ret >0 && ret <=4096)
        {
            write(pData,ret);
        }
        else if(ret == 0)
        {
            m_file.close();
            break;
        }
        else if(ret <0)
        {
            qDebug() <<"发送文件内容给客户端过程中失败";
            m_file.close();
            break;
        }
    }
    delete []pData;
    pData = nullptr;
}
